using System;
using System.Collections.Generic;
using System.Text;
using System.Collections ;


namespace BuildingStructuralElements.Sections
{
   
    internal  delegate void _onHeadersLoadhandler();
    
    /// <summary>
    /// 
    /// </summary>
    public class SectionManagerINSTANT : AbstractSectionManagerINSTANT
    {
        private static SectionManagerINSTANT instance;

        public static SectionManagerINSTANT Instance
        {
            get
            {
                if (instance == null)
                    instance = new SectionManagerINSTANT();
                return instance;

            }
        }

 
        internal  event _onHeadersLoadhandler onHeadersLoad;
        // Cashe memory .if a section is loaded there is no need to be reloaded.
        private Dictionary<string, Section> Cache;
        //names of the sections of one header(selected)
        private string[] _sectionsNames;
        //current section
        private Section _section;
        // names of the headers of directory 
        private string []  _headerNames;

        private Dictionary <string ,CSectionHeader > _HeadersCatalog;


        private CSectionHeader[] _headers;
        private int num_of_files;
        private SelectionDataStrategy _selectionDataStrategy;

        private CSectionFields _Fields;

        public CSectionFields  Fields
        {
            get { return _Fields; }
            set { _Fields = value; }
        }

	

        private String  path;

        override public String  Path
        {
            get { return path; }
            set { path = value; }
        }


        /// <summary>
        /// 
        /// </summary>
        override public string[] HeaderNames
        {
            get 
            {
                return _headerNames;

            }

        }

        private void fillHeadersNames()
        {
            _headerNames = new string[num_of_files];

            for (int h = 0; h < num_of_files; h++)
                _headerNames[h] = Headers[h].Name;
        }


        private  void fillNamesToHeaders()
        {
            _HeadersCatalog = new Dictionary<string, CSectionHeader>();

            //fill headers array
            for (int h = 0; h < num_of_files; h++)
                _HeadersCatalog.Add(Headers[h].Name, Headers[h]);
        }

        override public String[] SectionsNames
        {
            get { return _sectionsNames; }
        }

        public CSectionHeader[] Headers 
        {
            get { return _headers; }
        }

        public SectionManagerINSTANT()
        {
            this._section = new Section();
            Cache = new Dictionary<string, Section>(20);
            //subscription to onHeadLoad
            this.onHeadersLoad  += new _onHeadersLoadhandler(this.fillHeadersNames);
            this.onHeadersLoad += new _onHeadersLoadhandler(this.fillNamesToHeaders);

            
        }

        override public Section _Section
        {
            get
            {
                return this._section;

            }


        }

        override  public void LoadSectionFile(String path )
        {   
            num_of_files = 0;
            this.path = path;
            try
            {
                CSection_Facade.LoadCSectionFilesPath(path, 0);
                CSection_Facade.getNumOfSectionsFiles(ref num_of_files);

                if (num_of_files == 0)
                    throw new SectionDllException("There are no .SEC files in the specified directory");
            }
            catch { throw; }
        }

        [Obsolete ("Use second ovverload ",true )]
        override public void LoadSectionFile()
        {
            if (path.Length >0)
            {
                try
                {
                    CSection_Facade.LoadCSectionFilesPath(path, 0);
                }
                catch (Exception exp)
                {

                }
            }

        }

        override public void LoadHeaders()
        {

            if (num_of_files < int.MaxValue && num_of_files > 0)
            {
                _headers = new CSectionHeader[num_of_files];
                for (int h = 0; h < num_of_files; h++)
                {
                    _headers[h].Description = "";
                    _headers[h].Name = "";


                }

            }

            try
            {
                if (num_of_files > 0)
                {

                    CSection_Facade.getHeadersByIndex(_headers, num_of_files);
                    onHeadersLoad();
                }

       
            }
            catch (Exception exp)
            {

            }
        }

        private  Section ExecuteSelectionStrategy()
        {
            CSectionData _data;

            Section section = new Section();
            try
            {  
                _data = _selectionDataStrategy.getCSectionData();

                section.SectionData = _data;
                section.Name = _data.Name;
                return section;
              //  if(!Cache.ContainsKey (_Section.Name))
               // Cache.Add(_Section.Name, _Section);
            }
            catch (SectionDllException exp)
            {
                Console.WriteLine(exp.Message);

            }
            finally
            {
                
            }

            return null;

        }

        private CSectionFields LoadSectionFields(CSectionHeader selectedHeader)
        {
             Fields = new CSectionFields();
         
     
            if (selectedHeader.profileIndex != 0)
            {

                Fields.getFields(selectedHeader.profileIndex);
 
            }
            _Section.Fields = Fields;
            return Fields;

        }

        override public Section LoadSection(string name) 
        {
            if (Headers.Length > 0)
            {
                Section section;
                _selectionDataStrategy = new SelectionByName(name);

                CSectionFields Fields = LoadSectionFields(Headers[_selectionDataStrategy.SectionHeader]);

                section = ExecuteSelectionStrategy();
                section.Fields = Fields;
                return section;

            }
            return null;
        }

        override public void LoadSection(int profileIndex, int fileIndex)
        {
            if (Headers.Length > 0)
            {
                _selectionDataStrategy = new SelectionByIndexes(fileIndex, profileIndex);

                LoadSectionFields(Headers[_selectionDataStrategy.SectionHeader]);

                ExecuteSelectionStrategy();
            }
        }

        override public  void LoadSectionsNames(int profileIndex)
        {

            if (profileIndex > num_of_files)
                return;

            _sectionsNames= new string [Headers[profileIndex ].NumOfProfiles ];
            for (int i = 0; i < Headers[profileIndex].NumOfProfiles; i++)
            {
                _selectionDataStrategy = new SelectionByIndexes(profileIndex, i);
                this._sectionsNames  [i]=_selectionDataStrategy.getCSectionData().Name;

            }
            
        }

        /*

        override public void LoadSectionsNames(int profileIndex)
        {

            if (profileIndex > num_of_files)
                return;

            _sectionsNames = new string[Headers[profileIndex].NumOfProfiles];
            for (int i = 0; i < Headers[profileIndex].NumOfProfiles; i++)
            {
                _selectionDataStrategy = new SelectionByIndexes(profileIndex, i);
                this._sectionsNames[i] = _selectionDataStrategy.getCSectionData().Name;
            }

        }
        */

        public CSectionHeader  getHeader (string headerName)
        {
            if (headerName.Length == 0) throw new SectionDllException("headerName should not be empty");
            if (_HeadersCatalog.ContainsKey(headerName))
                return (CSectionHeader)_HeadersCatalog[headerName];
            else throw new SectionDllException("There is No Header with that name");

        }

        private int getHeaderPosition(string headerName)
        {
            if (headerName.Length == 0) throw new SectionDllException("headerName should not be empty");
            for (int i=0; i<Headers .Length ;i++)
            {
                if (Headers[i].Name == headerName)
                {
                    return i;
                }

            }
            return -1;
        }

        # region "Section"

        /*
        public CSectionData getCSectionData(string _sectionName,ref int csectionHeader)
        {

            CSectionData data;
            data = new CSectionData();
            data.m_Data = new double[100];
            data.Name = "NULL";

            try
            {
                CSection_Facade.GetSectionDataStructAndIndex(_sectionName, ref data, ref  csectionHeader);

            }
            catch (Exception exp)
            {
                Console.Write(exp.Message);
                throw (new SectionDllException("_Section Cannot be Loaded . Strategy Executed SelectionByName"));
            }
            finally
            {


            }

            return data;

        }

        public CSectionData getCSectionData(int profileIndex, int fileIndex,ref  int csectionHeader)
        {
            CSectionData data;
            data = new CSectionData();
            data.m_Data = new double[100];
            data.Name = "NULL";

            if (profileIndex >= 0)
            {
                try
                {
                    CSection_Facade.getDataStruct(ref data, 100, profileIndex, fileIndex);
                    csectionHeader = profileIndex;
                }
                catch (Exception exp)
                {
                    Console.Write(exp.Message);
                    throw (new SectionDllException("_Section Cannot be Loaded. Strategy Executed SelectionByIndexes"));
                }


            }

            return data;

        }
         * 
         * 
         * 

         override public void LoadSection(string name)
        {
            // if section already in cache then recall
            if (Cache.ContainsKey(name))
            {
                Section tempSection = Cache[name];
                this._section = tempSection;
            }
            else
            {

                if (Headers.Length > 0)
                {
                }
            }

        }

        override public void LoadSection(int profileIndex, int fileIndex)
        {

                if (Headers.Length > 0)
                {
                }
            
        }
        */

        public override bool ExistSection(string type, string name)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override  List<string> GetListOfSectionsNames()
        {
            List<string> sections = new List<string>();
            this.LoadHeaders();
            CSectionHeader[] headers = this.Headers;

            foreach (CSectionHeader header in headers)
            {
                this.LoadSectionsNames(0);
                if (this.SectionsNames != null)
                    foreach (string sect in this.SectionsNames)
                        sections.Add(sect);
            }
            return sections;
        }

        public override double GetSectionInertiaAttribute(string type , string name, string attribute)
        {
            string sectionname = type + name;
            Sections.Section section = this.LoadSection(sectionname);
            return section.getValueOf(attribute);
        }

        #endregion
    }



}
  
